﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Configuration;
using dotBASS;

namespace FX.CC.Andon.MusicService
{
    public partial class MusicSvc : ServiceBase
    {
        const string log_source = "Ty Music Service Log";

        Thread playTh, stopTh;
        IList<CtrlWrapper> ctrlList;

        string musicFolder;

        SYNCPROC mySync;
        AutoResetEvent syncObj;
        bool exitLoop = false;

        public MusicSvc()
        {
            InitializeComponent();
            if (!EventLog.SourceExists(log_source))
                EventLog.CreateEventSource(log_source, log_source);
        }

        protected override void OnStart(string[] args)
        {
            //read configuration
            musicFolder = ConfigurationManager.AppSettings["MusicFolder"];
            string ctrlStr = ConfigurationManager.AppSettings["CtrlTime"];
            ctrlList = new List<CtrlWrapper>();
            string[] tmpStrArr = ctrlStr.Split(',');
            foreach (var i in tmpStrArr)
            {
                var tmpArr = i.Split('~');
                var timePartFirstArr = tmpArr[0].Split(':');
                var obj = new CtrlWrapper();
                obj.StartHour = Convert.ToUInt16(timePartFirstArr[0]);
                obj.StartMin = Convert.ToUInt16(timePartFirstArr[1]);

                var timePartSecondArr = tmpArr[1].Split(':');
                obj.EndHour = Convert.ToUInt16(timePartSecondArr[0]);
                obj.EndMin = Convert.ToUInt16(timePartSecondArr[1]);

                ctrlList.Add(obj);
            }

            mySync = new SYNCPROC(EndSync);
            syncObj = new AutoResetEvent(false);
            playTh = new Thread(DoPlay);
            playTh.IsBackground = true;
            playTh.Start();

            stopTh = new Thread(DoStop);
            stopTh.IsBackground = true;
            stopTh.Start();

            EventLog.WriteEntry(log_source, "音乐播放服务已启动!", EventLogEntryType.Information);
        }


        protected override void OnStop()
        {
            EventLog.WriteEntry(log_source, "音乐播放服务已停止!", EventLogEntryType.Warning);
            try
            {
                exitLoop = true;
                syncObj.Set();

                Thread.Sleep(500);

                playTh.Abort();
                stopTh.Abort();

                BASS.BASS_Free();
                GC.Collect();
            }
            catch { }
        }

        void DoPlay()
        {
            Thread.Sleep(10 * 1000);
            while (true)
            {
                DateTime curTime = DateTime.Now;
                foreach (var ctrl in ctrlList)
                {
                    if (curTime.Hour == ctrl.StartHour && curTime.Minute == ctrl.StartMin)
                    {
                        if (!System.IO.Directory.Exists(musicFolder)) {
                            continue;
                        }

                        string[] allFiles = System.IO.Directory.GetFiles(musicFolder);
                         IList<string> mp3Files = allFiles.Where(p=>p.ToLower().EndsWith(".mp3")).ToList();
                         if (mp3Files.Count == 0) continue;
                        if (BASS.BASS_Init(-1, 44100, BASSInitFlags.BASS_DEVICE_DEFAULTS, IntPtr.Zero))
                        {
                            exitLoop = false;

                            EventLog.WriteEntry(log_source, string.Format("从{0}起，播放{1}首歌曲!", curTime.ToString("HH:mm"), mp3Files.Count.ToString()), 
                                EventLogEntryType.Information);

                            foreach (var musicFile in mp3Files)
                            {
                                if (exitLoop) {
                                    System.Diagnostics.Debug.WriteLine("强行跳出播放流程");
                                    //exitLoop = false;
                                    break; ;
                                }

                                syncObj.Reset();

                                UInt32 stream = BASS.BASS_StreamCreateFile(musicFile, 0, 0, BASSFlag.BASS_DEFAULT);
                                if (stream != 0)
                                {
                                    BASS.BASS_SetVolume(1);
                                    BASS.BASS_ChannelSetPosition(stream, 0, BASSPosMode.BASS_POS_BYTE);
                                    
                                    int syncHandler = BASS.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END, 0, mySync, IntPtr.Zero);
                                    BASS.BASS_ChannelPlay(stream, false);

                                    syncObj.WaitOne();
                                    bool removeOk = BASS.BASS_ChannelRemoveSync((int)stream, syncHandler);
                                    System.Diagnostics.Debug.WriteLine(removeOk ? "播放结束同步对象移除成功" : "播放结束同步对象移除失败");
                                    
                                    BASS.BASS_StreamFree(stream);
                                }
                                else
                                {
                                    Console.WriteLine(BASS.BASS_ErrorGetCode());
                                }
                            }


                            BASS.BASS_Free();
                        }
                    }
                }

                Thread.Sleep(60000);
            }
        }

        void DoStop()
        {
            Thread.Sleep(10 * 1000);
            while (true)
            {
                DateTime curTime = DateTime.Now;
                foreach (var ctrl in ctrlList)
                {
                    if (curTime.Hour == ctrl.EndHour && curTime.Minute == ctrl.EndMin)
                    {
                        exitLoop = true;
                        syncObj.Set();
                    }
                }

                Thread.Sleep(60000);
            }
        }

        void EndSync(int handle, int channel, int data, IntPtr user)
        {
            //Console.WriteLine("同学们，音乐播放完毕！。。。。");
            Thread.Sleep(3000);
            //bool removeOk = BASS.BASS_ChannelRemoveSync(channel, handle);
            syncObj.Set();
        }
    }
}
